package com.bckj.fastboot.upms.biz.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.bckj.fastboot.core.lang.exception.BusinessException;
import com.bckj.fastboot.core.redis.RedisOps;
import com.bckj.fastboot.security.util.SecurityUtils;
import com.bckj.fastboot.upms.api.constant.UpmsCacheConstant;
import com.bckj.fastboot.upms.api.constant.UpmsConstant;
import com.bckj.fastboot.upms.api.dto.SysUserQuery;
import com.bckj.fastboot.upms.api.dto.SysUserRequest;
import com.bckj.fastboot.upms.api.dto.UserAuthInfo;
import com.bckj.fastboot.upms.api.entity.SysUser;
import com.bckj.fastboot.upms.api.vo.SysUserVO;
import com.bckj.fastboot.upms.biz.core.perm.Perms;
import com.bckj.fastboot.upms.biz.core.perm.PermsHandler;
import com.bckj.fastboot.upms.biz.repository.SysUserRepository;
import com.bckj.fastboot.upms.biz.convert.SysUserConvert;
import com.bckj.fastboot.upms.biz.core.user.event.UserCacheEvent;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;


@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserService {

    private static final PasswordEncoder ENCODER = new BCryptPasswordEncoder();

	private final SysUserRepository sysUserRepository;
    private final SysUserConvert sysUserConvert;
    private final PermsHandler permsHandler;
    private final RedisOps redisOps;


    public List<SysUserVO> list(SysUserQuery query) {
        return sysUserRepository.getBaseMapper().list(query);
    }

    public boolean save(SysUserRequest request) {
        check(request);
        SysUser entity = sysUserConvert.request2Bean(request);
        entity.setPassword(ENCODER.encode(request.getPassword()));
        entity.setCreateId(SecurityUtils.getUserOrElseThrow().getId());
        return sysUserRepository.save(entity);
    }

    private void check(SysUserRequest request) {
        if (sysUserRepository.lambdaQuery().eq(SysUser::getUsername, request.getUsername()).eq(SysUser::getDeleteFlag, 0)
                .ne(request.getId() != null, SysUser::getId, request.getId()).count() > 0) {
            throw new BusinessException("用户名已存在");
        }
    }

    public boolean update(SysUserRequest request) {
        Long id = request.getId();
        check(request);
        boolean r = sysUserRepository.updateById(sysUserConvert.request2Bean(request));
        if (r) {
            SpringUtil.publishEvent(new UserCacheEvent(UpmsConstant.USER_TYPE_SU, id));
        }
        return r;
    }

    public SysUserVO details(Long id) {
        return sysUserConvert.bean2VO(sysUserRepository.getById(id));
    }

    public boolean enabled(Long id) {
        return false;
    }

    public boolean remove(Long id) {
        return false;
    }

    public UserAuthInfo findByUsername(String username) {
        UserAuthInfo result = sysUserRepository.getBaseMapper().findByUsername(username);
        if (result != null) {
            //
        }
        return result;
    }

    public boolean savePerms(SysUserRequest request) {
        Perms perms = new Perms(request.getId(), 1, request.getPermsType());
        if (StrUtil.isNotBlank(request.getDataSelect())) {
            permsHandler.trans(perms, request.getDataSelect(), true);
        }
        if (StrUtil.isNotBlank(request.getFilterSelect())) {
            permsHandler.trans(perms, request.getFilterSelect(), false);
        }
        permsHandler.savePerms(perms);
        return true;
    }

    public Set<SysUser> findByIds(Set<Long> ids) {
        Assert.notEmpty(ids, "用户id不能为空");
        List<Object> result = redisOps.hmget(UpmsCacheConstant.SYS_USER_KEY, ids.stream().map(Object::toString).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(result)) {
            return result.stream().filter(Objects::nonNull).map(p -> (SysUser) p).collect(Collectors.toSet());
        }
        return new HashSet<>();
    }
}

